/**
 *Copyright (c) 2024 watereyes
 * workflow is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.workflow.mobile.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import org.activiti.bpmn.model.FlowElement;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.beanutils.BeanUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;
import org.swan.bean.MessageBean;

import com.koron.util.Tools;
import com.koron.workflow.api.bean.CommunicatingBean;
import com.koron.workflow.api.bean.HistoryBillsBean;
import com.koron.workflow.api.bean.HistoryTaskMsgBean;
import com.koron.workflow.api.bean.RelationBean;
import com.koron.workflow.api.bean.SubHistoryBillsBean;
import com.koron.workflow.api.bean.query.RelationQueryBean;
import com.koron.workflow.api.dto.HistoryTaskMsgDto;
import com.koron.workflow.api.mapper.CommunicatingMapper;
import com.koron.workflow.api.mapper.HistoryBillsMapper;
import com.koron.workflow.api.mapper.HistoryTaskMsgMapper;
import com.koron.workflow.api.mapper.SubHistoryBillsMapper;
import com.koron.workflow.api.service.ActivitiService;
import com.koron.workflow.api.service.RelationService;
import com.koron.workflow.common.bean.StaffBean;
import com.koron.workflow.common.exception.WorkflowException;
import com.koron.workflow.common.util.BusinessCode;
import com.koron.workflow.common.util.DateUtils;
import com.koron.workflow.common.util.WorkflowUtil;
import com.koron.workflow.mobile.service.MobileService;

@Service
public class MobileServiceImpl implements MobileService {
	
	private static Logger log = LoggerFactory.getLogger(MobileServiceImpl.class);
	
	@Autowired
	private ActivitiService activitiService;
	
	@Autowired
	private RelationService relationService;

	@Override
	@TaskAnnotation("historyView")
	public MessageBean<?> historyView(SessionFactory factory, String setCode, String processCode, String processInstanceId) throws Exception {
		MessageBean<ModelAndView> message = MessageBean.create(BusinessCode.SUCCESS.getCode(), "查询成功", ModelAndView.class);
		HistoryBillsMapper historyBillMapper = factory.getMapper(HistoryBillsMapper.class);
		HistoryBillsBean historyBill = historyBillMapper.findByProcessInstanceId(processInstanceId);
		ModelAndView model = Tools.getView("history.btl");
		if(historyBill == null) {
			throw new WorkflowException("未找到单据信息");
		}
		HistoryTaskMsgMapper mapper = factory.getMapper(HistoryTaskMsgMapper.class);
		SubHistoryBillsMapper subMapper = factory.getMapper(SubHistoryBillsMapper.class);
		List<HistoryTaskMsgBean> historyTaskMsgs = mapper.findByProcessInstanceId(historyBill.getProcessInstanceId());
		List<HistoryTaskMsgBean> subHisTaskMsgs = new ArrayList<HistoryTaskMsgBean>();
		List<SubHistoryBillsBean> subBills = subMapper.findByParentProcessInstanceId(historyBill.getProcessInstanceId());
		subBills.stream().forEach(e -> subHisTaskMsgs.addAll(mapper.findByProcessInstanceId(e.getProcessInstanceId())));
		historyTaskMsgs.addAll(subHisTaskMsgs);
		historyTaskMsgs = historyTaskMsgs.stream().sorted(Comparator.comparing(HistoryTaskMsgBean::getOperationTime)).collect(Collectors.toList());
		List<HistoryTaskMsgDto> dtoList = new ArrayList<HistoryTaskMsgDto>();
		for(int i = 0; i < historyTaskMsgs.size(); i++) {
			HistoryTaskMsgBean task = historyTaskMsgs.get(i);
			HistoryTaskMsgDto dto = new HistoryTaskMsgDto();
			BeanUtils.copyProperties(dto, task);
			dto.setOperationTime(DateUtils.parseDate(task.getOperationTime(), "yyyy-MM-dd HH:mm:ss"));
			dtoList.add(dto);
		}
		List<Task> tasks = activitiService.getTaskByProcessInsId(processInstanceId);
		if(tasks == null || tasks.size() == 0) {
			model.addObject("isEnd", true);
		} else {
			String taskName = "";
			model.addObject("isEnd", false);
			for(Task task : tasks) {
				List<String> users = activitiService.getCandidateUsers(task.getId());
				List<StaffBean> staffs = WorkflowUtil.getStaffByAccount(users);
				List<String> usernames = staffs.stream().map(t -> t.getName()).collect(Collectors.toList());
				taskName = task.getName() + "(" + usernames + ")" + "," + taskName;
			}
			if(taskName.length() > 0) {
				taskName = taskName.substring(0, taskName.length() - 1);
			}
			model.addObject("taskName", taskName);
		}
		model.addObject("history", dtoList);
		message.setData(model);
		return message;
	}

	@Override
	@TaskAnnotation("approvalView")
	public MessageBean<?> approvalView(SessionFactory factory, String setCode, String processCode, String taskId, String operator) throws Exception{
		MessageBean<ModelAndView> message = MessageBean.create(BusinessCode.SUCCESS.getCode(), "查询成功", ModelAndView.class);
		ModelAndView model = Tools.getView("approval.btl");
		//1、审批
		model.addObject("viewType", "1");
		Task task = activitiService.getTaskById(taskId);
		if(task == null) {
			throw new WorkflowException("任务不存在");
		}
		SubHistoryBillsBean subBill = null;
		boolean isSub = false;
		String processInstanceId = task.getProcessInstanceId();
		String candidateUserNames = "";
		List<Task> tasks = activitiService.getTaskByProcessInsId(processInstanceId);
		if(tasks != null && tasks.size() > 0) {
			candidateUserNames = tasks.stream().map(t -> {
				List<String> candidateUsers = activitiService.getCandidateUsers(t.getId());
				String userName = candidateUsers.stream().map(e -> WorkflowUtil.getStaffByAccount(e).getName()).collect(Collectors.joining(","));
				return t.getName() + "(" + userName +")";
			}).collect(Collectors.joining(","));
		}
		
		// 2、添加沟通  取消沟通
		CommunicatingMapper communicatingMapper = factory.getMapper(CommunicatingMapper.class);
		List<CommunicatingBean> communicatings = communicatingMapper.findByTaskIdAndFrom(taskId, operator);
		if(communicatings != null && communicatings.size() > 0) {
			List<Map<String, String>> communicators = new ArrayList<Map<String, String>>();
			for(CommunicatingBean communicating : communicatings) {
				Map<String, String> map = new HashMap<String, String>();
				map.put("code", communicating.getTo());
				map.put("name", WorkflowUtil.getStaffByAccount(communicating.getTo()).getName());
				communicators.add(map);
			}
			model.addObject("viewType", "2");
			model.addObject("communicators", communicators);
		}
		
		// 3、回复
		RelationQueryBean relationQuery = new RelationQueryBean();
		relationQuery.setTaskId(taskId);
		relationQuery.setUserAccount(operator);
		relationQuery.setProcessInstanceId(processInstanceId);
		relationQuery.setRelation(RelationBean.R_REPLY);
		relationQuery.setStatus(RelationBean.STATUS_UNHANDLE);
		List<RelationBean> relations = relationService.listRelation(factory, relationQuery);
		if(relations != null && relations.size() > 0) {
			model.addObject("viewType", "3");
		}
		
		SubHistoryBillsMapper subMapper = factory.getMapper(SubHistoryBillsMapper.class);
		List<SubHistoryBillsBean> subBills2 = subMapper.findByParentProInsIdAndStatus(processInstanceId, 1);
		if(subBills2 != null && subBills2.size() > 0) {
			subBill = subBills2.get(0);
			processInstanceId = subBill.getProcessInstanceId();
		}
		List<HistoricTaskInstance> hisTasks = new ArrayList<HistoricTaskInstance>();
		if(subBill != null && task.getTaskDefinitionKey().equals("Process-task0")) {
			isSub = true;
			Task pTask = activitiService.getTaskById(subBill.getTaskId());
			hisTasks = activitiService.getHistoricTaskByProcessInsId(subBill.getParentProcessInstanceId());
			hisTasks.stream().filter(t -> !t.getTaskDefinitionKey().equals(pTask.getTaskDefinitionKey()));
		} else {
			hisTasks = activitiService.getHistoricTaskByProcessInsId(processInstanceId);
		}
		hisTasks = hisTasks.stream().sorted(Comparator.comparing(HistoricTaskInstance::getEndTime)).collect(Collectors.toList());
		Map<String, String> reback = new HashMap<String, String>();
		for(HistoricTaskInstance hisTask : hisTasks) {
			reback.put(hisTask.getTaskDefinitionKey(), hisTask.getName());
		}
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		if(!activitiService.isDraftNode(task)) {
			Set<Entry<String, String>>  set = reback.entrySet();
			for(Entry<String, String> entry : set) {
				Map<String, String> data = new HashMap<String, String>();
				data.put("nowactivitiId", isSub ? "1-" + entry.getKey() : entry.getKey());
				data.put("nowactivitiName", entry.getValue());
				list.add(data);
			}
		}
		Collection<FlowElement> flowElements = activitiService.getFlowElements(task.getProcessDefinitionId());
		model.addObject("reback", list);
		model.addObject("taskName", task.getName());
		model.addObject("candidateUserNames", candidateUserNames);
		model.addObject("processInstanceId", processInstanceId);
		model.addObject("setCode", setCode);
		model.addObject("processCode", processCode);
		model.addObject("taskId", task.getId());
		model.addObject("param", activitiService.nodeParam(task, flowElements));
		message.setData(model);
		return message;
	}
}
